<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="Ag8qS" id="Ag8qS"><span data-lake-id="u755bea81" id="u755bea81">典型回答</span></h1>
  <p data-lake-id="u3099306c" id="u3099306c"><br></p>
  <p data-lake-id="u8edcc883" id="u8edcc883"><span data-lake-id="u1296cf4b" id="u1296cf4b">工厂模式的主要功能就是帮助我们实例化对象的。</span><strong><span data-lake-id="uf82f0faa" id="uf82f0faa">之所以名字中包含工厂模式四个字，是因为对象的实例化过程是通过工厂实现的，是用工厂代替new操作的。</span></strong></p>
  <p data-lake-id="udcf9236b" id="udcf9236b"><strong><span data-lake-id="uf593fbb5" id="uf593fbb5">​</span></strong><br></p>
  <p data-lake-id="u3dc7f412" id="u3dc7f412"><span data-lake-id="u9e24bb42" id="u9e24bb42">这样做的好处是封装了对象的实例化细节，尤其是对于实例化较复杂或者对象的生命周期应该集中管理的情况。会给你系统带来更大的可扩展性和尽量少的修改量。</span></p>
  <p data-lake-id="uac729acb" id="uac729acb"><span data-lake-id="u46c492ea" id="u46c492ea">​</span><br></p>
  <p data-lake-id="u7fe0f048" id="u7fe0f048"><strong><span data-lake-id="u319e15cc" id="u319e15cc">工厂模式有三种，分别是简单工厂模式、工厂方法模式、抽象工厂模式。</span></strong><span data-lake-id="u3c3083d3" id="u3c3083d3">三种模式从前到后越来越抽象，也更具有一般性。</span></p>
  <p data-lake-id="uf02c155a" id="uf02c155a"><span data-lake-id="u302df212" id="u302df212">​</span><br></p>
  <p data-lake-id="u90d61828" id="u90d61828"><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/5378072/1668597637641-c28781ed-bc68-4b86-a320-fb76a032d444.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_44%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u65b92e1d" id="u65b92e1d"><br></p>
  <p data-lake-id="ued067fdd" id="ued067fdd"><br></p>
  <p data-lake-id="u86b70f87" id="u86b70f87"><strong><span data-lake-id="ucedc261b" id="ucedc261b">简单工厂 ：一个工厂创建所有具体产品。</span></strong><span data-lake-id="u0f41c546" id="u0f41c546">对于增加新的产品，主要是新增产品，就要修改工厂类。符合单一职责原则。不符合开放-封闭原则</span></p>
  <p data-lake-id="u6ec10fbd" id="u6ec10fbd"><span data-lake-id="u66277f1a" id="u66277f1a">​</span><br></p>
  <ul list="u4c194c98">
   <li fid="u6fbca51c" data-lake-id="uabb9d928" id="uabb9d928"><span data-lake-id="u36161a27" id="u36161a27">优点： </span></li>
  </ul>
  <ul list="u4c194c98" data-lake-indent="1">
   <li fid="ua3f8db54" data-lake-id="uaea7ae6f" id="uaea7ae6f"><span data-lake-id="u58444333" id="u58444333">1、屏蔽产品的具体实现，调用者只关心产品的接口。</span></li>
   <li fid="ua3f8db54" data-lake-id="u6f26bedd" id="u6f26bedd"><span data-lake-id="uee3abd53" id="uee3abd53">2、实现简单</span></li>
  </ul>
  <ul list="u4c194c98" start="2">
   <li fid="u6fbca51c" data-lake-id="u3bcf54d6" id="u3bcf54d6"><span data-lake-id="u43ba2643" id="u43ba2643">缺点： </span></li>
  </ul>
  <ul list="u4c194c98" data-lake-indent="1">
   <li fid="u00e9b4d0" data-lake-id="u4038ff61" id="u4038ff61"><span data-lake-id="uc6de53fa" id="uc6de53fa">1、增加产品，需要修改工厂类，不符合开放-封闭原则</span></li>
   <li fid="u00e9b4d0" data-lake-id="uec817398" id="uec817398"><span data-lake-id="u816fce0e" id="u816fce0e">2、工厂类集中了所有实例的创建逻辑，违反了高内聚责任分配原则</span></li>
  </ul>
  <p data-lake-id="u8b05d524" id="u8b05d524"><br></p>
  <p data-lake-id="u8a5b6a2a" id="u8a5b6a2a"><strong><span data-lake-id="ud4ebba52" id="ud4ebba52">工厂方法 ：一个工厂方法只创建一个具体产品。</span></strong><span data-lake-id="u89adbfa6" id="u89adbfa6">支持增加任意产品，新增产品时不需要更改已有的工厂，需要增加该产品对应的工厂。符合单一职责原则、符合开放-封闭原则。但是引入了复杂性</span></p>
  <p data-lake-id="u88980101" id="u88980101"><br></p>
  <ul list="u623c97db">
   <li fid="u21cb38dc" data-lake-id="u9688cb7d" id="u9688cb7d"><span data-lake-id="uca0d2fac" id="uca0d2fac">优点： </span></li>
  </ul>
  <ul list="u623c97db" data-lake-indent="1">
   <li fid="u2f35ab5f" data-lake-id="uc866685d" id="uc866685d"><span data-lake-id="u83c2cb3e" id="u83c2cb3e">1、继承了简单工厂模式的优点</span></li>
   <li fid="u2f35ab5f" data-lake-id="u190a9522" id="u190a9522"><span data-lake-id="uae251c19" id="uae251c19">2、符合开放-封闭原则</span></li>
  </ul>
  <ul list="u623c97db" start="2">
   <li fid="u21cb38dc" data-lake-id="u22148d5b" id="u22148d5b"><span data-lake-id="u3e65f629" id="u3e65f629">缺点： </span></li>
  </ul>
  <ul list="u623c97db" data-lake-indent="1">
   <li fid="u22d728b5" data-lake-id="u3880e39f" id="u3880e39f"><span data-lake-id="uc7d5155b" id="uc7d5155b">1、增加产品，需要增加新的工厂类，导致系统类的个数成对增加，在一定程度上增加了系统的复杂性。</span></li>
  </ul>
  <p data-lake-id="u0f70b3bf" id="u0f70b3bf"><br></p>
  <p data-lake-id="u18a18149" id="u18a18149"><span data-lake-id="ua0f36227" id="ua0f36227">抽象工厂 ：</span><strong><span data-lake-id="ua03ea840" id="ua03ea840">一个工厂方法只创建一类具体产品</span></strong><span data-lake-id="u9990941c" id="u9990941c">。增加新产品时，需要修改工厂，增加产品族时，需要增加工厂。符合单一职责原则，部分符合开放-封闭原则，降低了复杂性</span></p>
  <p data-lake-id="u88eef465" id="u88eef465"><br></p>
  <ul list="ude70b708">
   <li fid="u76369a22" data-lake-id="u8ed28a41" id="u8ed28a41"><span data-lake-id="u60b315e2" id="u60b315e2">优点： </span></li>
  </ul>
  <ul list="ude70b708" data-lake-indent="1">
   <li fid="ucb9e3e4b" data-lake-id="u4c7772d7" id="u4c7772d7"><span data-lake-id="u3d7d529d" id="u3d7d529d">1、隔离了具体类的生成，使得客户并不需要知道什么被创建</span></li>
   <li fid="ucb9e3e4b" data-lake-id="ue19d9188" id="ue19d9188"><span data-lake-id="ucd68b934" id="ucd68b934">2、每次可以通过具体工厂类创建一个产品族中的多个对象，增加或者替换产品族比较方便，增加新的具体工厂和产品族很方便；</span></li>
  </ul>
  <ul list="ude70b708" start="2">
   <li fid="u76369a22" data-lake-id="u27bfd14e" id="u27bfd14e"><span data-lake-id="u4426c552" id="u4426c552">缺点 </span></li>
  </ul>
  <ul list="ude70b708" data-lake-indent="1">
   <li fid="u4847f98d" data-lake-id="ue444a064" id="ue444a064"><span data-lake-id="u58a90932" id="u58a90932">增加新的产品等级结构很复杂，需要修改抽象工厂和所有的具体工厂类，对“开闭原则”的支持呈现倾斜性。</span></li>
  </ul>
  <p data-lake-id="u4fd5702e" id="u4fd5702e"><br></p>
  <h1 data-lake-id="iZqaM" id="iZqaM"><span data-lake-id="u8d5c3f68" id="u8d5c3f68">扩展知识</span></h1>
  <h2 data-lake-id="z4kK7" id="z4kK7"><span data-lake-id="u6a3a468c" id="u6a3a468c">简单工厂模式</span></h2>
  <p data-lake-id="uc0357b8b" id="uc0357b8b"><br></p>
  <p data-lake-id="ud47a71af" id="ud47a71af"><span data-lake-id="ub13abe6a" id="ub13abe6a">简单工厂模式是属于创建型模式，又叫做静态工厂方法（Static Factory Method）模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式，可以理解为是不同工厂模式的一个特殊实现。</span></p>
  <p data-lake-id="ud4d7275f" id="ud4d7275f"><br></p>
  <p data-lake-id="u77102646" id="u77102646"><span data-lake-id="u7e48052a" id="u7e48052a">在介绍简单工厂模式之前，我们尝试解决以下问题：</span></p>
  <p data-lake-id="uc32d0ee9" id="uc32d0ee9"><br></p>
  <p data-lake-id="ub7fa9583" id="ub7fa9583"><span data-lake-id="uebd009d9" id="uebd009d9">现在我们要使用面向对象的形式定义计算器，为了实现各算法之间的解耦。主要的用到的类如下：</span></p>
  <p data-lake-id="u11c827f7" id="u11c827f7"><br></p>
  <pre lang="java"><code>
// 计算类的基类
public abstract class Operation {

    private double value1 = 0;
    private double value2 = 0;

    public double getValue1() {
        return value1;
    }
    public void setValue1(double value1) {
        this.value1 = value1;
    }
    public double getValue2() {
        return value2;
    }
    public void setValue2(double value2) {
        this.value2 = value2;
    }
    protected abstract double getResule();
}

//加法
public class OperationAdd extends Operation {
    @Override
    protected double getResule() {
        return getValue1() + getValue2();
    }
}
//减法
public class OperationSub extends Operation {
    @Override
    protected double getResule() {
        return getValue1() - getValue2();
    }
}
//乘法
public class OperationMul extends Operation {
    @Override
    protected double getResule() {
        return getValue1() * getValue2();
    }
}
//除法
public class OperationDiv extends Operation {
    @Override
    protected double getResule() {
        if (getValue2() != 0) {
            return getValue1() / getValue2();
        }
        throw new IllegalArgumentException("除数不能为零");
    }
}
</code></pre>
  <p data-lake-id="uadc77418" id="uadc77418"><br></p>
  <p data-lake-id="u6d0042c2" id="u6d0042c2"><span data-lake-id="u955d7623" id="u955d7623">当我想要执行加法运算时，可以使用如下代码：</span></p>
  <p data-lake-id="u68601401" id="u68601401"><br></p>
  <pre lang="java"><code>
public class Main {
    public static void main(String[] args) {
        OperationAdd operationAdd = new OperationAdd();
        operationAdd.setValue1(10);
        operationAdd.setValue2(5);
System.out.println(operationAdd.getResule());
    }
}
</code></pre>
  <p data-lake-id="u39e86551" id="u39e86551"><br></p>
  <p data-lake-id="uceea4f18" id="uceea4f18"><span data-lake-id="uadf4eba1" id="uadf4eba1">当我需要执行减法运算时，我就要创建一个OperationSub类。也就是说，我想要使用不同的运算的时候就要创建不同的类，并且要明确知道该类的名字。</span></p>
  <p data-lake-id="uf62b5e36" id="uf62b5e36"><br></p>
  <p data-lake-id="ub7c07a09" id="ub7c07a09"><span data-lake-id="u99d2bffd" id="u99d2bffd">那么这种重复的创建类的工作其实可以放到一个统一的工厂类中。简单工厂模式有以下优点：</span></p>
  <p data-lake-id="u3b28e921" id="u3b28e921"><br></p>
  <blockquote data-lake-id="u0da57a7c" id="u0da57a7c">
   <p data-lake-id="ua15a7b45" id="ua15a7b45"><span data-lake-id="ufda30faa" id="ufda30faa">1、一个调用者想创建一个对象，只要知道其名称就可以了。</span></p>
   <p data-lake-id="u9249eeb7" id="u9249eeb7"><span data-lake-id="u2484f594" id="u2484f594"> </span></p>
   <p data-lake-id="ud30ffe4e" id="ud30ffe4e"><span data-lake-id="u9fe497c1" id="u9fe497c1">2、屏蔽产品的具体实现，调用者只关心产品的接口。</span></p>
  </blockquote>
  <p data-lake-id="u9f5222c4" id="u9f5222c4"><br></p>
  <h3 data-lake-id="vpP6d" id="vpP6d"><span data-lake-id="u6c676732" id="u6c676732">简单工厂模式实现方式</span></h3>
  <p data-lake-id="uce89ad80" id="uce89ad80"><br></p>
  <p data-lake-id="u1d9d3a9a" id="u1d9d3a9a"><span data-lake-id="u7e776953" id="u7e776953">简单工厂模式其实和他的名字一样，很简单。先来看看它的组成:</span></p>
  <p data-lake-id="udfff1c69" id="udfff1c69"><br></p>
  <blockquote data-lake-id="ub3f1a42d" id="ub3f1a42d">
   <p data-lake-id="ua3b873ed" id="ua3b873ed"><span data-lake-id="u5a34dae1" id="u5a34dae1">Factory:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由 一个具体类实现。（OperationFactory）</span></p>
   <p data-lake-id="u954c65a7" id="u954c65a7"><span data-lake-id="u2f2f2cce" id="u2f2f2cce"> </span></p>
   <p data-lake-id="uf578f7d8" id="uf578f7d8"><span data-lake-id="ue345800a" id="ue345800a">Product:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。（Operation）</span></p>
   <p data-lake-id="u039518ed" id="u039518ed"><span data-lake-id="u7083b330" id="u7083b330"> </span></p>
   <p data-lake-id="udd9fde7f" id="udd9fde7f"><span data-lake-id="u3775fd71" id="u3775fd71">ConcreteProduct:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 来用类图来清晰的表示下的它们之间的关系（OperationAdd\OperationSub等）</span></p>
  </blockquote>
  <p data-lake-id="uc8b88ae8" id="uc8b88ae8"><br></p>
  <p data-lake-id="ud3ef8833" id="ud3ef8833"><img src="http://www.hollischuang.com/wp-content/uploads/2019/05/15588649289622.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_41%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u3603e829" id="u3603e829">​</span></p>
  <p data-lake-id="ub39835ae" id="ub39835ae"><br></p>
  <p data-lake-id="u8008e84e" id="u8008e84e"><span data-lake-id="ubaebd46f" id="ubaebd46f">在原有类的基础上，定义工厂类：</span></p>
  <p data-lake-id="u8d754ac0" id="u8d754ac0"><br></p>
  <pre lang="java"><code>
//工厂类
public class OperationFactory {

    public static Operation createOperation(String operation) {
        Operation oper = null;
        switch (operation) {
            case "+":
                oper = new OperationAdd();
                break;
            case "-":
                oper = new OperationSub();
                break;
            case "*":
                oper = new OperationMul();
                break;

            case "/":
                oper = new OperationDiv();
                break;
            default:
                throw new UnsupportedOperationException("不支持该操作");
        }
        return oper;
    }
}
</code></pre>
  <p data-lake-id="ue995cf90" id="ue995cf90"><br></p>
  <p data-lake-id="ua3a9e780" id="ua3a9e780"><span data-lake-id="ube594419" id="ube594419">有了工厂类之后，可以使用工厂创建对象：</span></p>
  <p data-lake-id="u466e5299" id="u466e5299"><br></p>
  <pre lang="java"><code>
Operation operationAdd = OperationFactory.createOperation("+");
operationAdd.setValue1(10);
operationAdd.setValue2(5);
System.out.println(operationAdd.getResule());
</code></pre>
  <p data-lake-id="u25d39b86" id="u25d39b86"><br></p>
  <p data-lake-id="u7c87f126" id="u7c87f126"><span data-lake-id="ubd9d3e21" id="ubd9d3e21">通过简单工厂模式，该计算器的使用者不需要关心实现加法逻辑的那个类的具体名字，他只要知道该类对应的参数"+"就可以了。</span></p>
  <p data-lake-id="u249ae166" id="u249ae166"><br></p>
  <h3 data-lake-id="AJWKo" id="AJWKo"><span data-lake-id="u92fdec31" id="u92fdec31">简单工厂模式存在的问题</span></h3>
  <p data-lake-id="u64e0f09c" id="u64e0f09c"><br></p>
  <p data-lake-id="u8f343814" id="u8f343814"><span data-lake-id="u31a71d7f" id="u31a71d7f">当我们需要增加一种计算时，例如开平方。这个时候我们需要先定义一个类继承</span><code data-lake-id="uffb19c73" id="uffb19c73"><span data-lake-id="uc85db9af" id="uc85db9af">Operation</span></code><span data-lake-id="ufd491d69" id="ufd491d69">类，其中实现平方的代码。除此之外我们还要修改</span><code data-lake-id="u958b83d1" id="u958b83d1"><span data-lake-id="udf2b60d1" id="udf2b60d1">OperationFactory</span></code><span data-lake-id="u62ead8ee" id="u62ead8ee">类的代码，增加一个case。这显然是违背开闭原则的。可想而知对于新产品的加入，工厂类是很被动的。</span></p>
  <p data-lake-id="u4f51c5cc" id="u4f51c5cc"><br></p>
  <p data-lake-id="u12d469de" id="u12d469de"><span data-lake-id="u33724174" id="u33724174">我们举的例子是最简单的情况。而在实际应用中，很可能产品是一个多层次的树状结构。 简单工厂可能就不太适用了。</span></p>
  <p data-lake-id="u34658100" id="u34658100"><br></p>
  <h3 data-lake-id="vnilZ" id="vnilZ"><span data-lake-id="u33ecd70f" id="u33ecd70f">简单工厂模式总结</span></h3>
  <p data-lake-id="u9c097f09" id="u9c097f09"><br></p>
  <p data-lake-id="u1d5cb33c" id="u1d5cb33c"><span data-lake-id="u611f6285" id="u611f6285">工厂类是整个简单工厂模式的关键。包含了必要的逻辑判断，根据外界给定的信息，决定究竟应该创建哪个具体类的对象。通过使用工厂类，外界可以从直接创建具体产品对象的尴尬局面摆脱出来，仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的。明确了各自的职责和权利，有利于整个软件体系结构的优化。</span></p>
  <p data-lake-id="ue45272b0" id="ue45272b0"><br></p>
  <p data-lake-id="uad9b7e5d" id="uad9b7e5d"><span data-lake-id="uf4a8ff27" id="uf4a8ff27">但是由于工厂类集中了所有实例的创建逻辑，违反了高内聚责任分配原则，将全部创建逻辑集中到了一个工厂类中；它所能创建的类只能是事先考虑到的，如果需要添加新的类，则就需要改变工厂类了。</span></p>
  <p data-lake-id="ud6598064" id="ud6598064"><br></p>
  <p data-lake-id="u8f2a07b5" id="u8f2a07b5"><span data-lake-id="u78ac9a22" id="u78ac9a22">当系统中的具体产品类不断增多时候，可能会出现要求工厂类根据不同条件创建不同实例的需求．这种对条件的判断和对具体产品类型的判断交错在一起，很难避免模块功能的蔓延，对系统的维护和扩展非常不利；</span></p>
  <p data-lake-id="ua4f38af4" id="ua4f38af4"><br></p>
  <p data-lake-id="uc2c6c565" id="uc2c6c565"><span data-lake-id="uda7c3dd7" id="uda7c3dd7">这些缺点在工厂方法模式中得到了一定的解决。</span></p>
  <p data-lake-id="u6fc85513" id="u6fc85513"><br></p>
  <h2 data-lake-id="ovADj" id="ovADj"><span data-lake-id="ud699e795" id="ud699e795">工厂方法模式</span></h2>
  <p data-lake-id="u617c1ff7" id="u617c1ff7"><br></p>
  <p data-lake-id="u02fbd02d" id="u02fbd02d"><span data-lake-id="ub5727b05" id="ub5727b05">工厂方法模式(Factory Method Pattern)又称为工厂模式，也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式，它属于类创建型模式。</span></p>
  <p data-lake-id="u07475985" id="u07475985"><br></p>
  <p data-lake-id="ucea02753" id="ucea02753"><span data-lake-id="u1fd6418a" id="u1fd6418a">工厂方法模式是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样，它也是处理在不指定对象具体类型的情况下创建对象的问题。</span></p>
  <p data-lake-id="ua7ab6cfc" id="ua7ab6cfc"><br></p>
  <blockquote data-lake-id="u4cb6e276" id="u4cb6e276">
   <p data-lake-id="u7c287b26" id="u7c287b26"><span data-lake-id="u9573af19" id="u9573af19">工厂方法模式的实质是“定义一个创建对象的接口，但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”</span></p>
  </blockquote>
  <p data-lake-id="u4d0df2c7" id="u4d0df2c7"><br></p>
  <h3 data-lake-id="WE4p1" id="WE4p1"><span data-lake-id="u33c1dee5" id="u33c1dee5">工厂方法模式用途</span></h3>
  <p data-lake-id="u422bcee4" id="u422bcee4"><br></p>
  <p data-lake-id="u442ce830" id="u442ce830"><span data-lake-id="ub5529d7b" id="ub5529d7b">工厂方法模式和简单工厂模式虽然都是通过工厂来创建对象，他们之间最大的不同是——</span><strong><span data-lake-id="u989ecddc" id="u989ecddc">工厂方法模式在设计上完全完全符合“开闭原则”。</span></strong></p>
  <p data-lake-id="u0d6d557a" id="u0d6d557a"><br></p>
  <p data-lake-id="u31ce4ecc" id="u31ce4ecc"><span data-lake-id="ufcd5d06d" id="ufcd5d06d">在以下情况下可以使用工厂方法模式：</span></p>
  <p data-lake-id="u64641cea" id="u64641cea"><br></p>
  <blockquote data-lake-id="u2bc8d3aa" id="u2bc8d3aa">
   <p data-lake-id="ud15fd2c0" id="ud15fd2c0"><span data-lake-id="u103507ee" id="u103507ee">一个类不知道它所需要的对象的类：在工厂方法模式中，客户端不需要知道具体产品类的类名，只需要知道所对应的工厂即可，具体的产品对象由具体工厂类创建；客户端需要知道创建具体产品的工厂类。</span></p>
   <p data-lake-id="u090b5799" id="u090b5799"><span data-lake-id="u2bb1871b" id="u2bb1871b"> </span></p>
   <p data-lake-id="u81f9f3eb" id="u81f9f3eb"><span data-lake-id="uddd6e3f3" id="uddd6e3f3">一个类通过其子类来指定创建哪个对象：在工厂方法模式中，对于抽象工厂类只需要提供一个创建产品的接口，而由其子类来确定具体要创建的对象，利用面向对象的多态性和里氏代换原则，在程序运行时，子类对象将覆盖父类对象，从而使得系统更容易扩展。</span></p>
   <p data-lake-id="udc22eec3" id="udc22eec3"><span data-lake-id="u0a312db6" id="u0a312db6"> </span></p>
   <p data-lake-id="ue302c3c0" id="ue302c3c0"><span data-lake-id="ub0770cc2" id="ub0770cc2">将创建对象的任务委托给多个工厂子类中的某一个，客户端在使用时可以无须关心是哪一个工厂子类创建产品子类，需要时再动态指定，可将具体工厂类的类名存储在配置文件或数据库中。</span></p>
  </blockquote>
  <p data-lake-id="u625ed0ef" id="u625ed0ef"><br></p>
  <h3 data-lake-id="Z63dB" id="Z63dB"><span data-lake-id="ue177bcf3" id="ue177bcf3">工厂方法模式实现方式</span></h3>
  <p data-lake-id="ue867603d" id="ue867603d"><br></p>
  <p data-lake-id="u39cc062e" id="u39cc062e"><span data-lake-id="u734e4089" id="u734e4089">工厂方法模式包含如下角色：</span></p>
  <p data-lake-id="u8451d3e1" id="u8451d3e1"><br></p>
  <blockquote data-lake-id="u61dff672" id="u61dff672">
   <p data-lake-id="ud8a11cd5" id="ud8a11cd5"><span data-lake-id="uca07a892" id="uca07a892">Product：抽象产品（</span><code data-lake-id="uc49a9027" id="uc49a9027"><span data-lake-id="uf2ae8724" id="uf2ae8724">Operation</span></code><span data-lake-id="u84c520bd" id="u84c520bd">）</span></p>
   <p data-lake-id="u58194190" id="u58194190"><span data-lake-id="u4a914618" id="u4a914618"> </span></p>
   <p data-lake-id="u19104cc9" id="u19104cc9"><span data-lake-id="u1fdbdce0" id="u1fdbdce0">ConcreteProduct：具体产品(</span><code data-lake-id="u91401f8e" id="u91401f8e"><span data-lake-id="u3171f59c" id="u3171f59c">OperationAdd</span></code><span data-lake-id="uff9c060c" id="uff9c060c">)</span></p>
   <p data-lake-id="u33944b86" id="u33944b86"><span data-lake-id="uec374040" id="uec374040"> </span></p>
   <p data-lake-id="u3d8a1a14" id="u3d8a1a14"><span data-lake-id="ue8d377b2" id="ue8d377b2">Factory：抽象工厂(</span><code data-lake-id="u98b6ef8f" id="u98b6ef8f"><span data-lake-id="u7d3868f5" id="u7d3868f5">IFactory</span></code><span data-lake-id="uc7d94da1" id="uc7d94da1">)</span></p>
   <p data-lake-id="u0541055f" id="u0541055f"><span data-lake-id="u6e99984d" id="u6e99984d"> </span></p>
   <p data-lake-id="ucbdff651" id="ucbdff651"><span data-lake-id="uf7469942" id="uf7469942">ConcreteFactory：具体工厂(</span><code data-lake-id="u06b4e8cf" id="u06b4e8cf"><span data-lake-id="uf003e1c8" id="uf003e1c8">AddFactory</span></code><span data-lake-id="uddd888c9" id="uddd888c9">)</span></p>
  </blockquote>
  <p data-lake-id="u308d88a5" id="u308d88a5"><br></p>
  <p data-lake-id="u3987bc13" id="u3987bc13"><img src="http://www.hollischuang.com/wp-content/uploads/2019/05/15588647240804.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_44%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="ud6ae50da" id="ud6ae50da">​</span></p>
  <p data-lake-id="u1b356a45" id="u1b356a45"><br></p>
  <p data-lake-id="u55e6549f" id="u55e6549f"><span data-lake-id="u48a587f7" id="u48a587f7">这里还用计算器的例子。在保持</span><code data-lake-id="uc0d0c4a3" id="uc0d0c4a3"><span data-lake-id="u672ebe5f" id="u672ebe5f">Operation</span></code><span data-lake-id="uc3feb8a9" id="uc3feb8a9">，</span><code data-lake-id="uacdcf577" id="uacdcf577"><span data-lake-id="u38877690" id="u38877690">OperationAdd</span></code><span data-lake-id="uf850b614" id="uf850b614">，</span><code data-lake-id="u74958767" id="u74958767"><span data-lake-id="u47ade217" id="u47ade217">OperationDiv</span></code><span data-lake-id="u92cfad89" id="u92cfad89">，</span><code data-lake-id="ud345b3ba" id="ud345b3ba"><span data-lake-id="u64239e59" id="u64239e59">OperationSub</span></code><span data-lake-id="u9ae295b2" id="u9ae295b2">，</span><code data-lake-id="u942f6c28" id="u942f6c28"><span data-lake-id="u9490e0c3" id="u9490e0c3">OperationMul</span></code><span data-lake-id="u6f08af9a" id="u6f08af9a">等几个方法不变的情况下，修改简单工厂模式中的工厂类（</span><code data-lake-id="u9b85d280" id="u9b85d280"><span data-lake-id="u5f761a60" id="u5f761a60">OperationFactory</span></code><span data-lake-id="udc07afdd" id="udc07afdd">）。替代原有的那个"万能"的大工厂类，这里使用工厂方法来代替：</span></p>
  <p data-lake-id="ub980c565" id="ub980c565"><br></p>
  <pre lang="java"><code>
//工厂接口
public interface IFactory {
    Operation CreateOption();
}

//加法类工厂
public class AddFactory implements IFactory {
    public Operation CreateOption() {
        return new OperationAdd();
    }
}

//除法类工厂
public class DivFactory implements IFactory {
    public Operation CreateOption() {
        return new OperationDiv();
    }
}

//乘法类工厂
public class MulFactory implements IFactory {
    public Operation CreateOption() {
        return new OperationMul();
    }
}

//减法类工厂
public class SubFactory implements IFactory {
    public Operation CreateOption() {
        return new OperationSub();
    }
}
</code></pre>
  <p data-lake-id="u0f15d8cf" id="u0f15d8cf"><br></p>
  <p data-lake-id="ue6703aad" id="ue6703aad"><span data-lake-id="u41d39ed5" id="u41d39ed5">这样，在客户端中想要执行加法运算时，需要以下方式：</span></p>
  <p data-lake-id="u171fca93" id="u171fca93"><br></p>
  <pre lang="java"><code>
public class Main {

    public static void main(String[] args) {
        IFactory factory = new AddFactory();
        Operation operationAdd =  factory.CreateOption();
        operationAdd.setValue1(10);
        operationAdd.setValue2(5);
        System.out.println(operationAdd.getResult());
    }
}
</code></pre>
  <p data-lake-id="ud5ab0d1f" id="ud5ab0d1f"><br></p>
  <p data-lake-id="u95921129" id="u95921129"><span data-lake-id="u6ee47642" id="u6ee47642">到这里，一个工厂方法模式就已经写好了。</span></p>
  <p data-lake-id="u0dec83c5" id="u0dec83c5"><br></p>
  <p data-lake-id="u023ef6eb" id="u023ef6eb"><span data-lake-id="u925dcb3b" id="u925dcb3b">从代码量上看，这种工厂方法模式比简单工厂方法模式更加复杂。针对不同的操作（Operation）类都有对应的工厂。很多人会有以下疑问：</span></p>
  <p data-lake-id="u338e2188" id="u338e2188"><br></p>
  <blockquote data-lake-id="u506e2b20" id="u506e2b20">
   <p data-lake-id="u068bbdec" id="u068bbdec"><span data-lake-id="u4fe0ecfe" id="u4fe0ecfe">貌似工厂方法模式比简单工厂模式要复杂的多？</span></p>
   <p data-lake-id="u032299e6" id="u032299e6"><span data-lake-id="u145c09da" id="u145c09da"> </span></p>
   <p data-lake-id="uc69d15a7" id="uc69d15a7"><span data-lake-id="u4790130d" id="u4790130d">工厂方法模式和我自己创建对象没什么区别？为什么要多搞出一些工厂来？</span></p>
  </blockquote>
  <p data-lake-id="u0bc44f59" id="u0bc44f59"><br></p>
  <p data-lake-id="u4b669fcf" id="u4b669fcf"><span data-lake-id="u8c72d2d2" id="u8c72d2d2">下面就针对以上两个问题来深入理解一下工厂方法模式。</span></p>
  <p data-lake-id="ufd1761f7" id="ufd1761f7"><br></p>
  <h3 data-lake-id="RvKY2" id="RvKY2"><span data-lake-id="uf9ea7f01" id="uf9ea7f01">为什么要使用工厂来创建对象？</span></h3>
  <p data-lake-id="ucc581f61" id="ucc581f61"><br></p>
  <blockquote data-lake-id="uc09639ef" id="uc09639ef">
   <p data-lake-id="u0472756f" id="u0472756f"><span data-lake-id="ub2592916" id="ub2592916">封装对象的创建过程</span></p>
  </blockquote>
  <p data-lake-id="u04886f42" id="u04886f42"><br></p>
  <p data-lake-id="uc5db8a92" id="uc5db8a92"><span data-lake-id="u78817165" id="u78817165">在工厂方法模式中，工厂方法用来创建客户所需要的产品，同时还向客户</span><strong><span data-lake-id="u76c6aaea" id="u76c6aaea">隐藏了哪种具体产品类将被实例化这一细节，用户只需要关心所需产品对应的工厂，无须关心创建细节，甚至无须知道具体产品类的类名。</span></strong></p>
  <p data-lake-id="u5c08d753" id="u5c08d753"><br></p>
  <p data-lake-id="uefdeca22" id="uefdeca22"><span data-lake-id="u76a12f13" id="u76a12f13">基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。</span><strong><span data-lake-id="ub180837e" id="ub180837e">它能够使工厂可以自主确定创建何种产品对象，而如何创建这个对象的细节则完全封装在具体工厂内部。</span></strong><span data-lake-id="ua5cbf98e" id="ua5cbf98e">工厂方法模式之所以又被称为多态工厂模式，是因为所有的具体工厂类都具有同一抽象父类。</span></p>
  <p data-lake-id="u19609003" id="u19609003"><br></p>
  <h3 data-lake-id="OC4vx" id="OC4vx"><span data-lake-id="uf9fb80a8" id="uf9fb80a8">为什么每种对象要单独有一个工厂？</span></h3>
  <p data-lake-id="ueb754301" id="ueb754301"><br></p>
  <blockquote data-lake-id="ua3fd9fd1" id="ua3fd9fd1">
   <p data-lake-id="u01019b99" id="u01019b99"><span data-lake-id="uf31c4365" id="uf31c4365">符合『开放-封闭原则』</span></p>
  </blockquote>
  <p data-lake-id="u88112cf8" id="u88112cf8"><br></p>
  <p data-lake-id="u74c1639a" id="u74c1639a"><span data-lake-id="u63267289" id="u63267289">主要目的是为了解耦。在系统中加入新产品时，无须修改抽象工厂和抽象产品提供的接口，无须修改客户端，也无须修改其他的具体工厂和具体产品，而只要添加一个具体工厂和具体产品就可以了。这样，系统的可扩展性也就变得非常好，完全符合“开闭原则。</span></p>
  <p data-lake-id="u383bc8f1" id="u383bc8f1"><br></p>
  <p data-lake-id="ucd1b6362" id="ucd1b6362"><span data-lake-id="uc8faf052" id="uc8faf052">以上就是工厂方法模式的优点。但是，工厂模式也有一些不尽如人意的地方：</span></p>
  <p data-lake-id="ud10c4f57" id="ud10c4f57"><br></p>
  <blockquote data-lake-id="u23e86b94" id="u23e86b94">
   <p data-lake-id="udb9eea4f" id="udb9eea4f"><span data-lake-id="ua9b0998c" id="ua9b0998c">在添加新产品时，需要编写新的具体产品类，而且还要提供与之对应的具体工厂类，系统中类的个数将成对增加，在一定程度上增加了系统的复杂度，有更多的类需要编译和运行，会给系统带来一些额外的开销。</span></p>
   <p data-lake-id="udaed0d4e" id="udaed0d4e"><span data-lake-id="u89345be3" id="u89345be3"> </span></p>
   <p data-lake-id="u6caff7fa" id="u6caff7fa"><span data-lake-id="u890718aa" id="u890718aa">由于考虑到系统的可扩展性，需要引入抽象层，在客户端代码中均使用抽象层进行定义，增加了系统的抽象性和理解难度，且在实现时可能需要用到DOM、反射等技术，增加了系统的实现难度。</span></p>
   <p data-lake-id="u1ceb0e1d" id="u1ceb0e1d"><span data-lake-id="uc6a8be01" id="uc6a8be01"> </span></p>
   <p data-lake-id="u8a484b70" id="u8a484b70"><strong><span data-lake-id="uecdc70ae" id="uecdc70ae">工厂方法模式总结</span></strong></p>
  </blockquote>
  <p data-lake-id="u0165af5c" id="u0165af5c"><br></p>
  <p data-lake-id="u3bfe5aeb" id="u3bfe5aeb"><span data-lake-id="uc097f282" id="uc097f282">工厂方法模式是简单工厂模式的进一步抽象和推广。</span></p>
  <p data-lake-id="u0580ff43" id="u0580ff43"><br></p>
  <p data-lake-id="u9c962342" id="u9c962342"><span data-lake-id="u735edaae" id="u735edaae">由于使用了面向对象的多态性，工厂方法模式保持了简单工厂模式的优点，而且克服了它的缺点。</span></p>
  <p data-lake-id="udd8c2091" id="udd8c2091"><br></p>
  <p data-lake-id="uccbbd865" id="uccbbd865"><span data-lake-id="ub4012c55" id="ub4012c55">在工厂方法模式中，核心的工厂类不再负责所有产品的创建，而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口，而不负责产品类被实例化这种细节，这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。</span></p>
  <p data-lake-id="u0fd063b0" id="u0fd063b0"><br></p>
  <p data-lake-id="u84358616" id="u84358616"><span data-lake-id="u64027158" id="u64027158">工厂方法模式的主要优点是增加新的产品类时无须修改现有系统，并封装了产品对象的创建细节，系统具有良好的灵活性和可扩展性；其缺点在于增加新产品的同时需要增加新的工厂，导致系统类的个数成对增加，在一定程度上增加了系统的复杂性。</span></p>
  <p data-lake-id="u77186e03" id="u77186e03"><br></p>
  <h2 data-lake-id="hPvpD" id="hPvpD"><span data-lake-id="uc290f27b" id="uc290f27b">抽象工厂模式</span></h2>
  <p data-lake-id="u88d2564e" id="u88d2564e"><br></p>
  <p data-lake-id="u1bd4fc29" id="u1bd4fc29"><span data-lake-id="uce544712" id="uce544712">抽象工厂模式(Abstract Factory Pattern)：提供一个创建一系列相关或相互依赖对象的接口，而无须指定它们具体的类。抽象工厂模式又称为Kit模式，属于对象创建型模式。</span></p>
  <p data-lake-id="u83027c51" id="u83027c51"><br></p>
  <p data-lake-id="u98a13f36" id="u98a13f36"><span data-lake-id="ub67ad8c5" id="ub67ad8c5">抽象工厂模式提供了一种方式，可以将同一产品族的单独的工厂封装起来。在正常使用中，客户端程序需要创建抽象工厂的具体实现，然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道（或关心）它从这些内部的工厂方法中获得对象的具体类型，因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。</span></p>
  <p data-lake-id="u6978a5ba" id="u6978a5ba"><br></p>
  <p data-lake-id="u6779561e" id="u6779561e"><strong><span data-lake-id="u9e109a05" id="u9e109a05">产品族</span></strong></p>
  <p data-lake-id="ua67fe4dd" id="ua67fe4dd"><br></p>
  <p data-lake-id="ucd6b0ab6" id="ucd6b0ab6"><span data-lake-id="u74719cf5" id="u74719cf5">来认识下什么是产品族: 位于不同产品等级结构中,功能相关的产品组成的家族。如下面的例子，就有两个产品族：跑车族和商务车族。</span></p>
  <p data-lake-id="ub8b86011" id="ub8b86011"><br></p>
  <p data-lake-id="u385e7d48" id="u385e7d48"><img src="http://www.hollischuang.com/wp-content/uploads/2019/05/15588644956826.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_54%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u7ece3d47" id="u7ece3d47">​</span></p>
  <p data-lake-id="ud3873499" id="ud3873499"><br></p>
  <h3 data-lake-id="z2BkG" id="z2BkG"><span data-lake-id="u1ee29c1e" id="u1ee29c1e">抽象工厂模式用途</span></h3>
  <p data-lake-id="u20a202d4" id="u20a202d4"><br></p>
  <p data-lake-id="u9d6207f4" id="u9d6207f4"><span data-lake-id="u056e4b31" id="u056e4b31">抽象工厂模式和工厂方法模式一样，都符合开放-封闭原则。但是不同的是，工厂方法模式在增加一个具体产品的时候，都要增加对应的工厂。但是抽象工厂模式只有在新增一个类型的具体产品时才需要新增工厂。也就是说，工厂方法模式的一个工厂只能创建一个具体产品。而抽象工厂模式的一个工厂可以创建属于一类类型的多种具体产品。工厂创建产品的个数介于简单工厂模式和工厂方法模式之间。</span></p>
  <p data-lake-id="ucd2d8dee" id="ucd2d8dee"><br></p>
  <p data-lake-id="uf1d7bb79" id="uf1d7bb79"><span data-lake-id="u38bb4d04" id="u38bb4d04">在以下情况下可以使用抽象工厂模式：</span></p>
  <p data-lake-id="u1025260e" id="u1025260e"><br></p>
  <blockquote data-lake-id="u83d3edc1" id="u83d3edc1">
   <p data-lake-id="u1b616de1" id="u1b616de1"><span data-lake-id="u1c6c4a78" id="u1c6c4a78">一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节，这对于所有类型的工厂模式都是重要的。</span></p>
   <p data-lake-id="uce5fde2c" id="uce5fde2c"><span data-lake-id="ub19a8a20" id="ub19a8a20"> </span></p>
   <p data-lake-id="u3ce02d3c" id="u3ce02d3c"><span data-lake-id="u8de2c32c" id="u8de2c32c">系统中有多于一个的产品族，而每次只使用其中某一产品族。</span></p>
   <p data-lake-id="ud0baced9" id="ud0baced9"><span data-lake-id="u8c8c9a2f" id="u8c8c9a2f"> </span></p>
   <p data-lake-id="ubc7cb556" id="ubc7cb556"><span data-lake-id="ufc27051a" id="ufc27051a">属于同一个产品族的产品将在一起使用，这一约束必须在系统的设计中体现出来。</span></p>
   <p data-lake-id="u658e9056" id="u658e9056"><span data-lake-id="ua82f9c54" id="ua82f9c54"> </span></p>
   <p data-lake-id="u9e6f46c4" id="u9e6f46c4"><span data-lake-id="ua52c8385" id="ua52c8385">系统提供一个产品类的库，所有的产品以同样的接口出现，从而使客户端不依赖于具体实现。</span></p>
  </blockquote>
  <p data-lake-id="u60419447" id="u60419447"><br></p>
  <h3 data-lake-id="E2DGt" id="E2DGt"><span data-lake-id="u37e01fd4" id="u37e01fd4">抽象工厂模式实现方式</span></h3>
  <p data-lake-id="u327b533d" id="u327b533d"><br></p>
  <p data-lake-id="u134b79bb" id="u134b79bb"><span data-lake-id="u1acf8f71" id="u1acf8f71">抽象工厂模式包含如下角色：</span></p>
  <p data-lake-id="u81a2d881" id="u81a2d881"><br></p>
  <blockquote data-lake-id="uf2f24742" id="uf2f24742">
   <p data-lake-id="udd6878e3" id="udd6878e3"><span data-lake-id="u9cbba2ce" id="u9cbba2ce">AbstractFactory(抽象工厂)：用于声明生成抽象产品的方法</span></p>
   <p data-lake-id="uea633d51" id="uea633d51"><span data-lake-id="ua7b123cc" id="ua7b123cc"> </span></p>
   <p data-lake-id="u09adf6d4" id="u09adf6d4"><span data-lake-id="u9c22ee5b" id="u9c22ee5b">ConcreteFactory(具体工厂)：实现了抽象工厂声明的生成抽象产品的方法，生成一组具体产品，这些产品构成了一个产品族，每一个产品都位于某个产品等级结构中；</span></p>
   <p data-lake-id="u1b2165dc" id="u1b2165dc"><span data-lake-id="ue96c8b18" id="ue96c8b18"> </span></p>
   <p data-lake-id="u18711aa6" id="u18711aa6"><span data-lake-id="u7830dccb" id="u7830dccb">AbstractProduct(抽象产品)：为每种产品声明接口，在抽象产品中定义了产品的抽象业务方法；</span></p>
   <p data-lake-id="ubd1b5662" id="ubd1b5662"><span data-lake-id="uaaf716ba" id="uaaf716ba"> </span></p>
   <p data-lake-id="u44c81d37" id="u44c81d37"><span data-lake-id="ub2e8027d" id="ub2e8027d">Product(具体产品)：定义具体工厂生产的具体产品对象，实现抽象产品接口中定义的业务方法。</span></p>
  </blockquote>
  <p data-lake-id="u5a69add3" id="u5a69add3"><br></p>
  <p data-lake-id="u21965a2f" id="u21965a2f"><span data-lake-id="u17c621c9" id="u17c621c9">本文的例子采用一个汽车代工厂造汽车的例子。假设我们是一家汽车代工厂商，我们负责给奔驰和特斯拉两家公司制造车子。我们简单的把奔驰车理解为需要加油的车，特斯拉为需要充电的车。其中奔驰车中包含跑车和商务车两种，特斯拉同样也包含跑车和商务车。</span></p>
  <p data-lake-id="ue01039f3" id="ue01039f3"><br></p>
  <p data-lake-id="u44ab6ef4" id="u44ab6ef4"><img src="http://www.hollischuang.com/wp-content/uploads/2019/05/15588645213493.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_51%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u98a6d7dc" id="u98a6d7dc">​</span></p>
  <p data-lake-id="ub626781f" id="ub626781f"><br></p>
  <p data-lake-id="u1c57eb5f" id="u1c57eb5f"><span data-lake-id="ud73d7962" id="ud73d7962">以上场景，我们就可以把跑车和商务车分别对待，对于跑车有单独的工厂创建，商务车也有单独的工厂。这样，以后无论是再帮任何其他厂商造车，只要是跑车或者商务车我们都不需要再引入工厂。同样，如果我们要增加一种其他类型的车，比如越野车，我们也不需要对跑车或者商务车的任何东西做修改。</span></p>
  <p data-lake-id="ud0e83703" id="ud0e83703"><br></p>
  <p data-lake-id="ub10bd8ab" id="ub10bd8ab"><span data-lake-id="ubc5dd458" id="ubc5dd458">下面是抽象产品，奔驰车和特斯拉车：</span></p>
  <p data-lake-id="u246be89f" id="u246be89f"><br></p>
  <pre lang="java"><code>
public interface BenzCar {
    //加汽油
    public void gasUp();

}

public interface TeslaCar {
    //充电
    public void charge();
}
</code></pre>
  <p data-lake-id="u5c36b20a" id="u5c36b20a"><br></p>
  <p data-lake-id="ud06e2027" id="ud06e2027"><span data-lake-id="u840fa8d4" id="u840fa8d4">下面是具体产品，奔驰跑车、奔驰商务车、特斯拉跑车、特斯拉商务车：</span></p>
  <p data-lake-id="u8d0b2d9b" id="u8d0b2d9b"><br></p>
  <pre lang="java"><code>
public class BenzSportCar implements BenzCar {
    public void gasUp() {
        System.out.println("给我的奔驰跑车加最好的汽油");
    }
}

public class BenzBusinessCar implements BenzCar{
    public void gasUp() {
        System.out.println("给我的奔驰商务车加一般的汽油");
    }
}

public class TeslaSportCar implements TeslaCar {
    public void charge() {
        System.out.println("给我特斯拉跑车冲满电");
    }
}

public class TeslaBusinessCar implements TeslaCar {
    public void charge() {
        System.out.println("不用给我特斯拉商务车冲满电");
    }
}
</code></pre>
  <p data-lake-id="u07cb740f" id="u07cb740f"><br></p>
  <p data-lake-id="uc2f72c07" id="uc2f72c07"><span data-lake-id="u80f4d33f" id="u80f4d33f">下面是抽象工厂：</span></p>
  <p data-lake-id="u2414cba8" id="u2414cba8"><br></p>
  <pre lang="java"><code>
public interface CarFactory {

    public BenzCar getBenzCar();
    public TeslaCar getTeslaCar();
}
</code></pre>
  <p data-lake-id="u69cff201" id="u69cff201"><br></p>
  <p data-lake-id="u3f8fad15" id="u3f8fad15"><span data-lake-id="u688d7a29" id="u688d7a29">下面是具体工厂：</span></p>
  <p data-lake-id="u9a749e64" id="u9a749e64"><br></p>
  <pre lang="java"><code>
public class SportCarFactory implements CarFactory {
    public BenzCar getBenzCar() {
        return new BenzSportCar();
    }

    public TeslaCar getTeslaCar() {
        return new TeslaSportCar();
    }
}

public class BusinessCarFactory implements CarFactory {
    public BenzCar getBenzCar() {
        return new BenzBusinessCar();
    }

    public TeslaCar getTeslaCar() {
        return new TeslaBusinessCar();
    }
}
</code></pre>
  <p data-lake-id="u1da88cbd" id="u1da88cbd"><br></p>
  <h3 data-lake-id="MwLSi" id="MwLSi"><span data-lake-id="ubf8ef3a9" id="ubf8ef3a9">“开闭原则”的倾斜性</span></h3>
  <p data-lake-id="u7749ce49" id="u7749ce49"><br></p>
  <p data-lake-id="ued9daf67" id="ued9daf67"><span data-lake-id="ufd2d492e" id="ufd2d492e">“开闭原则”要求系统对扩展开放，对修改封闭，通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统，其功能增强包括两方面：</span></p>
  <p data-lake-id="u809e6e8e" id="u809e6e8e"><br></p>
  <blockquote data-lake-id="u7ce0a65f" id="u7ce0a65f">
   <p data-lake-id="u9c0ac11e" id="u9c0ac11e"><span data-lake-id="u7e82ad92" id="u7e82ad92">增加产品族：对于增加新的产品族，工厂方法模式很好的支持了“开闭原则”，对于新增加的产品族，只需要对应增加一个新的具体工厂即可，对已有代码无须做任何修改。</span></p>
   <p data-lake-id="ucbfabe07" id="ucbfabe07"><span data-lake-id="u1c09072d" id="u1c09072d"> </span></p>
   <p data-lake-id="u0345fa81" id="u0345fa81"><span data-lake-id="u1d9f39fb" id="u1d9f39fb">增加新的产品等级结构：对于增加新的产品等级结构，需要修改所有的工厂角色，包括抽象工厂类，在所有的工厂类中都需要增加生产新产品的方法，不能很好地支持“开闭原则”。</span></p>
  </blockquote>
  <p data-lake-id="u346a7f3a" id="u346a7f3a"><br></p>
  <p data-lake-id="ue3ba53b9" id="ue3ba53b9"><span data-lake-id="u221ed276" id="u221ed276">抽象工厂模式的这种性质称为“开闭原则”的倾斜性，抽象工厂模式以一种倾斜的方式支持增加新的产品，它为新产品族的增加提供方便，但不能为新的产品等级结构的增加提供这样的方便。</span></p>
  <p data-lake-id="uaf012530" id="uaf012530"><br></p>
  <h3 data-lake-id="VOEfL" id="VOEfL"><span data-lake-id="u43ac8f3c" id="u43ac8f3c">抽象工厂模式总结</span></h3>
  <p data-lake-id="u9be9d654" id="u9be9d654"><br></p>
  <p data-lake-id="ueb48c462" id="ueb48c462"><span data-lake-id="u7b696c55" id="u7b696c55">抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口，而无须指定它们具体的类。抽象工厂模式又称为Kit模式，属于对象创建型模式。</span></p>
  <p data-lake-id="u994082ba" id="u994082ba"><br></p>
  <p data-lake-id="uef5adbb9" id="uef5adbb9"><span data-lake-id="u0590deab" id="u0590deab">抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。</span></p>
  <p data-lake-id="u25b17996" id="u25b17996"><br></p>
  <p data-lake-id="u714addb0" id="u714addb0"><span data-lake-id="u0a043583" id="u0a043583">抽象工厂模式的主要优点是隔离了具体类的生成，使得客户并不需要知道什么被创建，而且每次可以通过具体工厂类创建一个产品族中的多个对象，增加或者替换产品族比较方便，增加新的具体工厂和产品族很方便；主要缺点在于增加新的产品等级结构很复杂，需要修改抽象工厂和所有的具体工厂类，对“开闭原则”的支持呈现倾斜性。</span></p>
  <p data-lake-id="u77e8fb3a" id="u77e8fb3a"><br></p>
 </body>
</html>